library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

package our_types is
  type display_type is record
    min1 : unsigned(3 downto 0);
    min0 : unsigned(3 downto 0);
    sec1 : unsigned(3 downto 0);
    sec0 : unsigned(3 downto 0);
    hun1 : unsigned(3 downto 0);
    hun0 : unsigned(3 downto 0);
  end record display_type;
end package our_types;

--------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.our_types.all;

entity stopwatch is
  port( start_stop, lap_reset, clk100kHz : in std_logic;
        sw_display : out display_type := ("0000", "0000", "0000", "0000", "0000", "0000") );

--  check : assert not(start_stop and lap_reset) report "Incorrect use, both start/stop and lap/reset cannot be ON at same time"; 
  
end entity stopwatch;

architecture behavioral of stopwatch is
begin
  sw_beh : process(clk100kHz) is
    variable current_time_in_deci_seconds : integer := 0;
    variable current_time_in_seconds : integer :=0;
    variable current_time_in_minutes : integer :=0;
    variable deci_sec: integer:=0;
    variable sec: integer:=0;
    variable min: integer:=0;
    variable deci_tick: integer :=0;
    variable start_stop_press_count:integer :=0;
    variable ss_pressed: bit:='0';
    variable lap_reset_press_count: integer :=0;
    variable lr_pressed: bit:='0';
    variable sw_lap_reset:bit:='0';
    variable transfer_to_display: bit:='0';  
  begin
    if rising_edge(clk100kHz) then

      if start_stop='1'and ss_pressed='0'then
        ss_pressed :='1';
      end if;
      
      if ss_pressed='1' and start_stop='0'then
        start_stop_press_count := start_stop_press_count + 1;
        ss_pressed:='0';
      end if;
      
      if lap_reset='1'and lr_pressed='0'then
        lr_pressed :='1';
      end if;
      
      if lr_pressed='1' and lap_reset='0'then
        lap_reset_press_count := lap_reset_press_count + 1;
        lr_pressed:='0';
        sw_lap_reset:='1';
      end if;
      
      
      if (start_stop_press_count mod 2)=1 then
        
        deci_tick := deci_tick + 1;
        if (deci_tick mod 1000)= 0 then
          current_time_in_deci_seconds:= current_time_in_deci_seconds + 1;
        end if;
        
      else

        transfer_to_display:='0';
        if sw_lap_reset='1'then
          
          deci_tick :=0;
          current_time_in_deci_seconds:=0;
          sw_display <= ("0000","0000","0000","0000","0000","0000");
          
        end if;
        
      end if;
      
      if (lap_reset_press_count mod 2) =0 then
        transfer_to_display:='1';
      else
        transfer_to_display:='0';
      end if;
      
      if transfer_to_display='1'then
            
            current_time_in_seconds:=current_time_in_deci_seconds/100;
            current_time_in_minutes:=current_time_in_seconds/60;
          
            deci_sec := current_time_in_deci_seconds mod 100;
            sw_display.hun1 <= to_unsigned(deci_sec mod 10,4);
            sw_display.hun0 <= to_unsigned(deci_sec / 10,4);
            
            sec := current_time_in_seconds mod 60;
            sw_display.sec1 <= to_unsigned(sec mod 10,4);
            sw_display.sec0 <= to_unsigned(sec / 10,4);
                        
            min := current_time_in_minutes mod 60;
            sw_display.min1 <= to_unsigned(min mod 10,4);
            sw_display.min0 <= to_unsigned(min / 10,4);

      end if;        
        
    end if;
    
  end process sw_beh;
end architecture behavioral;

--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


entity clk_gen is
end entity clk_gen;

architecture clk_gen_arch of clk_gen is
    signal clk: std_logic;
begin
  clock_gen : process is
  begin
    clk <='1' after 0.05 us, '0' after 0.01 us;
    wait until clk='0';
  end process clock_gen;
end architecture clk_gen_arch;
   